import json
import redis
from typing import Optional, Any, Dict, List
import os

class RedisHelper:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(RedisHelper, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        if not hasattr(self, 'initialized'):
            # 读取配置文件
            config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config.json')
            with open(config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
            
            # 初始化Redis连接
            redis_config = config.get('redis', {})
            self.redis_client = redis.Redis(
                host=redis_config.get('host', 'localhost'),
                port=redis_config.get('port', 6379),
                db=redis_config.get('db', 0),
                password=redis_config.get('password'),
                decode_responses=False  # 修改：关闭自动解码
            )
            self.initialized = True

    def set_json(self, key: str, data: Dict[str, Any], expire: Optional[int] = None) -> bool:
        """
        存储JSON数据到Redis
        :param key: Redis键
        :param data: 要存储的字典数据
        :param expire: 过期时间(秒)，可选
        :return: 是否成功
        """
        try:
            json_data = json.dumps(data, ensure_ascii=False).encode('utf-8')
            self.redis_client.set(key, json_data)
            if expire:
                self.redis_client.expire(key, expire)
            return True
        except Exception as e:
            print(f"Redis set error: {str(e)}")
            return False

    def get_json(self, key: str) -> Optional[Dict[str, Any]]:
        """
        从Redis获取JSON数据
        :param key: Redis键
        :return: 字典数据或None
        """
        try:
            data = self.redis_client.get(key)
            if data:
                try:
                    # 查找JSON数据的开始位置 {
                    json_start = data.find(b'{')
                    if json_start >= 0:
                        # 只取JSON部分的数据
                        json_data = data[json_start:]
                        # 尝试UTF-8解码
                        decoded_data = json_data.decode('utf-8')
                        return json.loads(decoded_data)
                    return None
                except Exception as e:
                    print(f"Redis get error: {str(e)}")
                    return None
            return None
        except Exception as e:
            print(f"Redis get error: {str(e)}")
            return None

    def delete(self, key: str) -> bool:
        """
        删除Redis中的数据
        :param key: Redis键
        :return: 是否成功
        """
        try:
            return bool(self.redis_client.delete(key))
        except Exception as e:
            print(f"Redis delete error: {str(e)}")
            return False

    def update_json(self, key: str, data: Dict[str, Any]) -> bool:
        """
        更新Redis中的JSON数据
        :param key: Redis键
        :param data: 要更新的字典数据
        :return: 是否成功
        """
        try:
            existing_data = self.get_json(key)
            if existing_data:
                existing_data.update(data)
                return self.set_json(key, existing_data)
            return False
        except Exception as e:
            print(f"Redis update error: {str(e)}")
            return False

    def exists(self, key: str) -> bool:
        """
        检查键是否存在
        :param key: Redis键
        :return: 是否存在
        """
        try:
            return bool(self.redis_client.exists(key))
        except Exception as e:
            print(f"Redis exists error: {str(e)}")
            return False

    def set_json_with_hash(self, hash_key: str, key: str, data: Dict[str, Any]) -> bool:
        """
        使用Hash结构存储JSON数据
        :param hash_key: Hash的键
        :param key: Hash中的字段名
        :param data: 要存储的字典数据
        :return: 是否成功
        """
        try:
            json_data = json.dumps(data, ensure_ascii=False)
            return bool(self.redis_client.hset(hash_key, key, json_data))
        except Exception as e:
            print(f"Redis hash set error: {str(e)}")
            return False

    def get_json_from_hash(self, hash_key: str, key: str) -> Optional[Dict[str, Any]]:
        """
        从Hash结构中获取JSON数据
        :param hash_key: Hash的键
        :param key: Hash中的字段名
        :return: 字典数据或None
        """
        try:
            data = self.redis_client.hget(hash_key, key)
            return json.loads(data) if data else None
        except Exception as e:
            print(f"Redis hash get error: {str(e)}")
            return None

    def get_all_from_hash(self, hash_key: str) -> Dict[str, Dict[str, Any]]:
        """
        获取Hash中所有的JSON数据
        :param hash_key: Hash的键
        :return: 包含所有字段和值的字典
        """
        try:
            result = {}
            all_data = self.redis_client.hgetall(hash_key)
            for key, value in all_data.items():
                result[key] = json.loads(value)
            return result
        except Exception as e:
            print(f"Redis hash getall error: {str(e)}")
            return {}
